﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Random = System.Random;

namespace HXu.BaseTools
{
    /// <summary>
    /// RandomTools 随机数工具 <br />
    /// /************************************************* <br />
    /// -- 内容：<br />
    ///     1A、从若干个值中随机取一个值。<br />
    ///     1B、在 X 到 Y（包含） 之间随机取 count 个 整数。<br />
    ///     1C、随机从 list 列表中下标为 minIndex 到 maxIndex 的元素中取出 count个 组成新的 list 列表。<br />
    /// <br />
    ///     2A、返回一个小于1的随机浮点数。<br />
    ///     3B、返回一个随机颜色Color类型。<br />
    ///     2C、返回一个单位随机二维向量。<br />
    ///     2D、返回一个单位随机三维向量。<br />
    ///     2E、返回一个随机整数，在min(包含)和max(不包含)之间。<br />
    ///     2F、返回一个随机浮点数，在min(包含)和max(包含)之间。此时包括临界值。<br />
    /// <br />
    /// -- 使用方法：<br />
    ///     1、引用命名空间，直接调用。<br />
    /// *************************************************/ <br />
    /// </summary>
    public static class RandomTools
    {
        /// <summary>
        /// 1A、从若干个值中随机取一个值
        /// </summary>
        /// <typeparam name="T">值类型</typeparam>
        /// <param name="value">值</param>
        /// <returns></returns>
        public static T GetRandomValueFrom<T>(params T[] value)
        {
            var valueIndex = UnityEngine.Random.Range(0, value.Length);
            return value[valueIndex];
        }

        /// <summary>
        /// 1B、在 X 到 Y（包含） 之间随机取 count 个 整数
        /// </summary>
        /// <param name="X">最小值</param>
        /// <param name="Y">最大值</param>
        /// <param name="count">个数</param>
        /// <returns>存放随机数的链表</returns>
        public static List<int> GetRandomValue(int X, int Y, int count)
        {
            var minValue = X;
            var maxValue = Y;
            if (minValue >= maxValue)
                throw new Exception("minValue == maxValue");

            if (maxValue - minValue + 1 < count) 
                throw new Exception("count out of");

            Random random = new Random();

            List<int> values = new List<int>();

            while (values.Count < count)
            {
                int value = random.Next(minValue, maxValue + 1);

                if (values.Contains(value)) continue;

                values.Add(value);
            }

            return values;
        }

        /// <summary>
        /// 1C、随机从 list列表 中下标为 minIndex 到 maxIndex 的元素中取出 count个 组成新的 list
        /// </summary>
        /// <typeparam name="T">list 列表元素类型</typeparam>
        /// <param name="list">目标列表</param>
        /// <param name="minIndex">最小下标</param>
        /// <param name="maxIndex">最大下标</param>
        /// <param name="count">个数</param>
        /// <returns>结果列表</returns>
        public static List<T> GetRandomFromList<T>(this List<T> list, int minIndex, int maxIndex, int count)
        {
            List<int> listOfIndex = GetRandomValue(minIndex, maxIndex, count);

            return listOfIndex.Select(t => list[t]).ToList();
        }

        /// <summary>
        /// 2A、返回一个小于 1 的随机浮点数
        /// </summary>
        /// <returns></returns>
        public static float RandomFloat => UnityEngine.Random.value;

        /// <summary>
        /// 2B、返回一个随机颜色 Color 类型
        /// </summary>
        /// <returns></returns>
        public static Color RandomColor => new Color(RandomFloat, RandomFloat, RandomFloat);

        /// <summary>
        /// 2C、返回一个单位随机二维向量
        /// </summary>
        /// <returns></returns>
        public static Vector2 RandomVector2 => UnityEngine.Random.insideUnitCircle;

        /// <summary>
        /// 2D、返回一个单位随机三维向量
        /// </summary>
        /// <returns></returns>
        public static Vector3 RandomVector3 => UnityEngine.Random.insideUnitSphere;

        /// <summary>
        /// 2E、返回一个随机整数，在min(包含)和max(不包含)之间
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static int RandomIntNum(int min, int max) => UnityEngine.Random.Range(min, max);//[min,max) 

        /// <summary>
        /// 2F、返回一个随机浮点数，在min(包含)和max(包含)之间。此时包括临界值
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static float RandomFloatNum(float min, float max) => UnityEngine.Random.Range(min, max);//[min,max]
    }
}
